package com.evil.kingdom.task.timer;

import com.evil.common.core.util.StreamUtil;
import com.evil.kingdom.handler.timer.BattleTimerTaskHandler;
import com.evil.kingdom.pojo.dto.person.base.PersonDto;
import com.evil.kingdom.pojo.dto.person.general.GeneralDto;
import com.evil.kingdom.pojo.entity.action.Battle;
import com.evil.kingdom.pojo.entity.action.BattleLayout;
import com.evil.kingdom.pojo.entity.action.BattlePerson;
import com.evil.kingdom.pojo.entity.action.Battlefield;
import com.evil.kingdom.pojo.entity.base.Fight;
import com.evil.kingdom.pojo.entity.tactics.Tactics;
import com.evil.kingdom.utils.tactics.TacticsUtil;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Timer;

/**
 * 战场 定时器
 *
 * @author liyang
 * @date 2024-06-11 14:32
 */
@Slf4j
public class BattlefieldTimerTask extends BaseTimerTask<Battlefield, BattlefieldTimerTask, Boolean> {
    public static final Logger battlefieldLogger = LoggerFactory.getLogger("KINGDOM_BATTLEFIELD_LOGGER");

    private final BattleTimerTaskHandler battleTimerTaskHandler;

    public BattlefieldTimerTask(BattleTimerTaskHandler battleTimerTaskHandler, Timer timer, Battlefield battlefield, StopCallback<BattlefieldTimerTask> stopCallback, RunCallback<Battlefield, BattlefieldTimerTask, Boolean> runCallback) {
        super(timer, battlefield, stopCallback, runCallback);
        this.battleTimerTaskHandler = battleTimerTaskHandler;
    }

    public static BattlefieldTimerTask build(BattleTimerTaskHandler battleTimerTaskHandler, @NotNull(message = "出征不能为空") @Valid Battlefield battlefield, StopCallback<BattlefieldTimerTask> stopCallback, RunCallback<Battlefield, BattlefieldTimerTask, Boolean> runCallback) {
        Timer newTimer = new Timer();
        BattlefieldTimerTask battlefieldTimerTask = new BattlefieldTimerTask(battleTimerTaskHandler, newTimer, battlefield, stopCallback, runCallback);
        // 定时器延迟0毫秒后开始执行任务，之后每1000毫秒秒执行一次
        newTimer.schedule(battlefieldTimerTask, 0, 1000);
        return battlefieldTimerTask;
    }

    @Override
    public BattlefieldTimerTask get() {
        return this;
    }

    @Override
    public Boolean task() {
        Battlefield battlefield = this.getT();

        if (null == battlefield.getOffensiveGeneral() || null == battlefield.getDefensiveGeneral()) {
            if (null == battlefield.getTime()) {
                battlefield.setTime(0);
            }
            battlefield.setTime(battlefield.getTime() + 1);

            if (battlefield.getTime() >= 3) {
                battlefield.setTime(0);
                this.calOffensiveGeneral(battlefield).ifPresent(offensiveGeneral -> {
                    battlefield.setOffensiveGeneral(offensiveGeneral);
                    // 进攻方战术
                    battlefield.setOffensiveTactics(StreamUtil.getFirst(offensiveGeneral.getTactics(), null));
                });
                this.calDefensiveGeneral(battlefield).ifPresent(defensiveGeneral -> {
                    battlefield.setDefensiveGeneral(defensiveGeneral);
                    // 防守方战术
                    battlefield.setDefensiveTactics(StreamUtil.getFirst(defensiveGeneral.getTactics(), null));
                });

                if (null == battlefield.getOffensiveGeneral() || null == battlefield.getDefensiveGeneral()) {
                    this.stop();
                    return null == battlefield.getDefensiveGeneral();
                }

                // 构建战斗
                ArrayList<BattlePerson<?>> list = new ArrayList<>();
                BattleLayout layout = new BattleLayout();
                Fight none = Fight.none();
                // 初始化攻击方
                this.initBattle(list, layout, none, true);
                // 初始化防守方
                this.initBattle(list, layout, none, false);

                battlefieldLogger.info("battlefield|task|layout:{}", layout.printInfo());
                List<Battle> battles = StreamUtil.transListT(list, e -> new Battle(none, e, layout));
                // 构建战斗
                battlefield.setBattleTimerTasks(battleTimerTaskHandler.buildBattleTimerTask(battles, this::deadNameCallback));
                this.pause();
            }
        }

        return null;
    }

    /**
     * 计算进攻出场武将
     *
     * @param battlefield battlefield
     * @return GeneralDto
     */
    public Optional<GeneralDto> calOffensiveGeneral(Battlefield battlefield) {
        // 目前暂时随机出场
        return battlefield.getOffensiveGenerals().stream().filter(e -> e.getHp() > 0).findFirst();
    }

    /**
     * 计算防守出场武将
     *
     * @param battlefield battlefield
     * @return GeneralDto
     */
    public Optional<GeneralDto> calDefensiveGeneral(Battlefield battlefield) {
        // 目前暂时随机出场
        return battlefield.getDefensiveGenerals().stream().filter(e -> e.getHp() > 0).findFirst();
    }

    /**
     * 初始化战斗基础数据
     *
     * @param list        人物列表
     * @param layout      布局
     * @param addition    战场加成
     * @param isOffensive 是否攻击方
     */
    public void initBattle(ArrayList<BattlePerson<?>> list, BattleLayout layout, Fight addition, boolean isOffensive) {
        Battlefield battlefield = this.getT();
        GeneralDto generalDto = isOffensive ? battlefield.getOffensiveGeneral() : battlefield.getDefensiveGeneral();
        Tactics tactics = isOffensive ? battlefield.getOffensiveTactics() : battlefield.getDefensiveTactics();
        // 当前人物列表
        ArrayList<PersonDto> offensivePersons = new ArrayList<>();
        offensivePersons.add(generalDto);
        offensivePersons.addAll(generalDto.getSoldierSet());

        BattleLayout currentLayout = TacticsUtil.layout(tactics, offensivePersons, addition, isOffensive);
        // 纳入人物总列表
        list.addAll(currentLayout.keySet());
        // 当前人物列表构建布局
        layout.putAll(currentLayout);
    }

    /**
     * 人物死亡回调
     *
     * @param deadName 死亡人物名称
     */
    public void deadNameCallback(String deadName) {
        Battlefield battlefield = this.getT();
        if (StringUtils.isNotBlank(deadName)) {
            boolean deadOffensive = deadName.equals(battlefield.getOffensiveGeneral().getName());
            boolean deadDefensive = deadName.equals(battlefield.getDefensiveGeneral().getName());
            battlefield.setOffensiveGeneral(null);
            battlefield.setDefensiveGeneral(null);
            // 攻击主帅 或者 防守主帅 死亡
            if (deadOffensive || deadDefensive) {
                battlefieldLogger.info("battlefield|task|finished|result:{}", deadDefensive);
                battlefield.getBattleTimerTasks().forEach(BaseTimerTask::stop);
                // 死亡与主帅对比：是进攻主帅=战场败北结束，是防守主帅=战场胜利结束
                this.getRunCallback().callback(battlefield, this, deadDefensive);
                battlefield.setTime(0);
                this.restart();
            }
        }
    }
}
